package main;

import static org.junit.Assert.*;



import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class ScienceStoreImplTest {
	ScienceStoreImpl store;
	@Before
	public void setUp() throws Exception {
		store = new ScienceStoreImpl();
	}

	@After
	public void tearDown() throws Exception {
		
	}

	@Test
	public void testBuyEquipment() {
		
	}

	@Test
	public void testBuyLab() {
		
	}

	@Test
	public void testBuyScientist() {
		
	}

	@Test
	public void testBrowseEquipment() {
		boolean sorted = true;
		for(int i=0;sorted==true && i<store.getEquipmentLength("pc")-1;i++)
			sorted = store.getEquipmentAtIndex("pc", i).getPrice() <=store.getEquipmentAtIndex("pc", i+1).getPrice();
			//test invariant
		assertTrue(sorted);
		Pack<Integer> notenough = store.browseEquipment("pc", 1000);
		//test post condition
		assertNull(notenough);
		Pack<Integer> onepack = store.browseEquipment("pc", 1);
		assertNotNull(onepack);
		assertTrue(onepack.getIndex()==0 && onepack.getPrice()== store.getEquipmentAtIndex("pc", 0).getPrice() && onepack.getData() == store.getEquipmentAtIndex("pc", 0).getData());
		Pack<Integer> twopack = store.browseEquipment("pc", 5);
		assertNotNull(twopack);
		int amount=0;
		int price=0;
		//test post condition
		for(int i=0;i<=twopack.getIndex();i++)
			amount=amount+store.getEquipmentAtIndex("pc", i).getData();
		for(int i=0;i<=twopack.getIndex();i++)
			price=price+store.getEquipmentAtIndex("pc", i).getData();
		//test post condition
		assertTrue(onepack.getIndex()>0 && onepack.getPrice()== price && onepack.getData() == amount && onepack.getData()>=5);
		for(int i = 0;sorted==true && i<store.getEquipmentLength("pc")-1;i++)
			sorted = store.getEquipmentAtIndex("pc", i).getPrice() <=store.getEquipmentAtIndex("pc", i+1).getPrice();
		//test invariant
		assertTrue(sorted);
	}

	@Test
	public void testBrowseLab() {
		boolean sorted = true;
		for(int i=0;sorted==true && i<store.getLabLength("programmer")-1;i++)
			sorted = store.getLabAtIndex("programmer", i).getPrice() <=store.getLabAtIndex("programmer", i+1).getPrice();
			//test invariant
		assertTrue(sorted);
		Pack<Lab> firstlab = store.getLabAtIndex("programmer", 0);
		assertEquals(firstlab, store.browseLab("programmer"));
		for(int i=0;sorted==true && i<store.getLabLength("programmer")-1;i++)
			sorted = store.getLabAtIndex("programmer", i).getPrice() <=store.getLabAtIndex("programmer", i+1).getPrice();
			//test invariant
		assertTrue(sorted);
		
	}

	@Test
	public void testBrowseScientist() {
		boolean sorted = true;
		for(int i=0;sorted==true && i<store.getScientistLength("programmer")-1;i++)
			sorted = store.getScientistAtIndex("programmer", i).getPrice() <=store.getScientistAtIndex("programmer", i+1).getPrice();
			//test invariant
		assertTrue(sorted);
		Pack<Scientist> firstpack = store.getScientistAtIndex("programmer", 0);
		assertEquals(firstpack, store.browseScientist("programmer"));
		
		for(int i=0;sorted==true && i<store.getScientistLength("programmer")-1;i++)
			sorted = store.getScientistAtIndex("programmer", i).getPrice() <=store.getScientistAtIndex("programmer", i+1).getPrice();
			//test invariant
		assertTrue(sorted);		
	}

	@Test
	public void testSellEquipment() {
		boolean sorted = true;
		for(int i=0;sorted==true && i<store.getEquipmentLength("pc")-1;i++)
			sorted = store.getEquipmentAtIndex("pc", i).getPrice() <=store.getEquipmentAtIndex("pc", i+1).getPrice();
			//test invariant
		assertTrue(sorted);
		boolean caught = false;
		try {
			store.sellEquipment("notexists",0);
		} catch (Exception e) {
			caught=true;
		}
		//check precondition
		assertTrue(caught);
		int preLen = store.getEquipmentLength("pc");
		Pack<Integer> equipment6 = store.getEquipmentAtIndex("pc",6);
		caught=false;
		try {
			store.sellEquipment("pc",-5);
		} catch (Exception e) {
			caught=true;
			
		}
		//test post condition, sell one pack
		assertTrue(preLen==store.getEquipmentLength("pc")+1 && equipment6.equals(store.getEquipmentAtIndex("pc", 5)) && !caught);
		preLen = store.getEquipmentLength("pc");
		equipment6 = store.getEquipmentAtIndex("pc",6);
		caught=false;
		try {
			store.sellEquipment("pc",5);
		} catch (Exception e) {
			caught=true;
			
		}
		//test post condition, sell many packs
		assertTrue(preLen==store.getEquipmentLength("pc")+6 && equipment6.equals(store.getEquipmentAtIndex("pc", 0)) && !caught);
		for(int i=0;sorted==true && i<store.getEquipmentLength("pc")-1;i++)
			sorted = store.getEquipmentAtIndex("pc", i).getPrice() <=store.getEquipmentAtIndex("pc", i+1).getPrice();
			//test invariant
		assertTrue(sorted);
	}

	@Test
	public void testSellLab() {
		boolean sorted = true;
		for(int i=0;sorted==true && i<store.getLabLength("programmer")-1;i++)
			sorted = store.getLabAtIndex("programmer", i).getPrice() <=store.getLabAtIndex("programmer", i+1).getPrice();
			//test invariant
		assertTrue(sorted);
	
		boolean caught = false;
		try {
			store.sellLab("notexists");
		} catch (Exception e) {
			caught=true;
		}
		//check precondition
		assertTrue(caught);
		int preLen = store.getLabLength("programmer");
		Pack<Lab> Lab1 = store.getLabAtIndex("programmer",1);
		caught=false;
		try {
			store.sellLab("programmer");
		} catch (Exception e) {
			caught=true;
			
		}
		//test post condition
		assertTrue(preLen==store.getLabLength("programmer")+1 && Lab1.equals(store.getLabAtIndex("programmer", 0)) && !caught);
	
		for(int i=0;sorted==true && i<store.getLabLength("programmer")-1;i++)
			sorted = store.getLabAtIndex("programmer", i).getPrice() <=store.getLabAtIndex("programmer", i+1).getPrice();
			//test invariant
		assertTrue(sorted);
		
	}

	@Test
	public void testSellScientist() {
		boolean sorted = true;
		for(int i=0;sorted==true && i<store.getScientistLength("programmer")-1;i++)
			sorted = store.getScientistAtIndex("programmer", i).getPrice() <=store.getScientistAtIndex("programmer", i+1).getPrice();
			//test invariant
		assertTrue(sorted);
		boolean caught = false;
		try {
			store.sellScientist("notexists");
		} catch (Exception e) {
			caught=true;
		}
		//check precondition
		assertTrue(caught);
		int preLen = store.getScientistLength("programmer");
		Pack<Scientist> nerd1 = store.getScientistAtIndex("programmer",1);
		caught=false;
		try {
			store.sellScientist("programmer");
		} catch (Exception e) {
			caught=true;
			
		}
		//test post condition
		assertTrue(preLen==store.getScientistLength("programmer")+1 && nerd1.equals(store.getScientistAtIndex("programmer", 0)) && !caught);
		for(int i=0;sorted==true && i<store.getScientistLength("programmer")-1;i++)
			sorted = store.getScientistAtIndex("programmer", i).getPrice() <=store.getScientistAtIndex("programmer", i+1).getPrice();
			//test invariant
		assertTrue(sorted);
	}

	@Test
	public void testCharge() {
		Statistics stats = new Statistics(10);
		int preBudget = stats.getBudget();
		/*ScienceStoreImpl storeCpy = new ScienceStoreImpl(store);*/
		store.charge(100, stats);
		//post test
		assertEquals(preBudget-100,stats.getBudget());
		//Invariant test
		/*assertEquals(storeCpy, store);*/
	}

}
